#include "postgislinker.h"
#include "ui_postgislinker.h"
#include <QMessageBox>
#include <QStandardItemModel>
#include <QStandardItem>
#include "geoobject.h"
#include "geopoint.h"
#include "geolinestring.h"
#include "geopolygon.h"
#include "geomultipolygon.h"


postGISLinker::postGISLinker(QWidget *parent):
        QWidget(parent),
        ui(new Ui::postGISLinker)
{
    ui->setupUi(this);
    this->model = new QSqlQueryModel();
    this->propertieModel = new QSqlQueryModel();
    this->setWindowTitle("PostGIS");
    layer=new geoLayer();
    db = QSqlDatabase::addDatabase("QPSQL");
    connect(ui->Link_Button,&QPushButton::clicked,this,&postGISLinker::slotLink);
    connect(ui->Paint_Button,&QPushButton::clicked,this,&postGISLinker::toDraw);
    connect(ui->Cancel_Button,&QPushButton::clicked,this,&postGISLinker::close);
    connect(ui->Tables_listView,&QAbstractItemView::clicked,this,&postGISLinker::changeDrawMap);
}

postGISLinker::~postGISLinker()
{
    delete ui;
    delete model;
    if(db.isOpen())
        db.close();
}

void postGISLinker::slotLink()
{
    if(ui->Username_lineEdit->text().isEmpty()){
        QMessageBox::information(this,"warning","用户名为空！");
        return;
    }
    if(ui->Password_lineEdit->text().isEmpty()){
        QMessageBox::information(this,"warning","密码为空！");
        return;
    }
    if(ui->Hostname_lineEdit->text().isEmpty()){
        QMessageBox::information(this,"warning","Hostname 为空！");
        return;
    }
    if(ui->Port_lineEdit->text().isEmpty()){
        QMessageBox::information(this,"warning","Port 为空！");
        return;
    }else{
        if(ui->Port_lineEdit->text().toInt()<=0){
            QMessageBox::information(this,"warning","输入正确的Port");
            return;
        }
    }
    if(ui->Database_lineEdit->text().isEmpty()){
        QMessageBox::information(this,"warning","Database 为空！");
        return;
    }
    db.setHostName(ui->Hostname_lineEdit->text());
    db.setPassword(ui->Password_lineEdit->text());
    db.setUserName(ui->Username_lineEdit->text());
    db.setPort(ui->Port_lineEdit->text().toInt());
    db.setDatabaseName(ui->Database_lineEdit->text());
    if(db.open()){
        setTablesList();
    }else{
        QMessageBox::information(this,"warning","连接失败！");
        return;
    }
}



void postGISLinker::setTablesList()
{
    QStringList ss = db.tables(QSql::TableType::Tables);
    QStringList result = ss.filter("tiger.");
    result.append(ss.filter("topology."));
    result.append(ss.filter("spatial_"));
    result.append(ss.filter("pointcloud_"));
    for (int i=0;i<result.count();i++) {
        ss.removeOne(result.at(i));
    }
    ItemModel = new QStandardItemModel(this);
    for (int i=0;i<ss.count();i++) {
        QStandardItem *item = new QStandardItem(ss.at(i));
        ItemModel->appendRow(item);
    }
    ui->Tables_listView->setModel(ItemModel);
    ui->Tables_listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->Tables_listView->setSelectionMode(QAbstractItemView::SelectionMode::MultiSelection);
}

void postGISLinker::processRecord(QByteArray wkb)
{
        OGRSpatialReference osr;//用GDAL定义投影的类
        OGRGeometry *geom = nullptr;

        // Parse WKB

        OGRErr err = OGRGeometryFactory::createFromWkb((unsigned char*)wkb.constData(), &osr, &geom);
        if (err != OGRERR_NONE){
            // process error, like emit signal
        }

        // Analyse geometry by type and process them as you wish
        OGRwkbGeometryType type = wkbFlatten(geom->getGeometryType());
        switch(type) {
        case wkbLineString: {
            //线
            geoObject* obj = new geoLineString();
            layer->geoObjects.append(obj);
            OGRLineString* poPolyline = static_cast<OGRLineString*>(geom);
            for(int ipoint=0;ipoint<poPolyline->getNumPoints();ipoint++){
                obj->coordinates.append(QPointF(poPolyline->getX(ipoint),poPolyline->getY(ipoint)));
                obj->projectedCoordinates.append(QPointF(poPolyline->getX(ipoint),poPolyline->getY(ipoint)));
            }
            obj->type="LineString";
                break;
        }
        case wkbPoint:{
            //点
            OGRPoint* poPoint = static_cast<OGRPoint*>(geom);
            geoObject* obj = new geoPoint();
            layer->geoObjects.append(obj);
            obj->coordinates.append(QPointF(poPoint->getX(),poPoint->getY()));
            obj->projectedCoordinates.append(QPointF(poPoint->getX(),poPoint->getY()));
            obj->type="Point";
            break;
        }
        case wkbPolygon:{
            //面
            geoObject* obj = new geoPolygon();
            layer->geoObjects.append(obj);

            OGRPolygon* poPolygon = static_cast<OGRPolygon*>(geom);
            OGRLinearRing* poLinearRing =  poPolygon->getExteriorRing();
            for(int ipoint=0;ipoint<poLinearRing->getNumPoints();ipoint++)
            {
                 obj->coordinates.append(QPointF(poLinearRing->getX(ipoint),poLinearRing->getY(ipoint)));
                 obj->projectedCoordinates.append(QPointF(poLinearRing->getX(ipoint),poLinearRing->getY(ipoint)));
            }
            obj->type="Polygon";
            break;
        }
        case wkbMultiPolygon:{
            //多面
            geoObject* obj = new geoMultiPolygon();
            layer->geoObjects.append(obj);
            OGRMultiPolygon* poMultiPolygon = static_cast<OGRMultiPolygon*>(geom);
            OGRPolygon* poPolygon;
            geoPolygon *geopolygon=new geoPolygon();

            for(int ipolygon=0;ipolygon<poMultiPolygon->getNumGeometries();ipolygon++){
                poPolygon = static_cast<OGRPolygon*>(poMultiPolygon->getGeometryRef(ipolygon));
                OGRLinearRing* poLinearRing =  poPolygon->getExteriorRing();
                for(int ipoint=0;ipoint<poLinearRing->getNumPoints();ipoint++){
                geopolygon->coordinates.append(QPointF(poLinearRing->getX(ipoint),poLinearRing->getY(ipoint)));
                geopolygon->projectedCoordinates.append(QPointF(poLinearRing->getX(ipoint),poLinearRing->getY(ipoint)));

                }
                static_cast<geoMultiPolygon*>(obj)->polygons.append(geopolygon);
            }
            obj->type="MultiPolygon";

            break;
        }
        case wkbMultiLineString:{
            //线
            geoObject* obj = new geoLineString();
            OGRLineString* poLineString = static_cast<OGRLineString*>(geom);
            for(int ipoint=0;ipoint<poLineString->getNumPoints();ipoint++){
                 obj->coordinates.append(QPointF(poLineString->getX(ipoint),poLineString->getY(ipoint)));
                 obj->projectedCoordinates.append(QPointF(poLineString->getX(ipoint),poLineString->getY(ipoint)));

            }
            obj->type="LineString";
            layer->geoObjects.append(obj);
            break;
        }
        default:
            break;
            // process error, like emit signal
        }
        // Clean-up
        OGRGeometryFactory::destroyGeometry(geom);
}

void postGISLinker::toDraw()
{
    QStringList ss = db.tables(QSql::TableType::Tables);
    QStringList result = ss.filter("tiger.");
    result.append(ss.filter("topology."));
    result.append(ss.filter("spatial_"));
    result.append(ss.filter("pointcloud_"));
    for (int i=0;i<result.count();i++) {
        ss.removeOne(result.at(i));
    }
    QString filePath=ss.at(drawIndex);
    model->setQuery(QString("SELECT gid, ST_AsBinary(geom) AS geom FROM %1").arg(filePath),db);//选中请求表中的gid
    for(int i=0;i<model->rowCount();i++)
    {
        QByteArray wkb=model->record(i).value("geom").toByteArray();
        processRecord(wkb);
    }
    layer->name=filePath;

    drawNow(layer);
}

void postGISLinker::changeDrawMap(QModelIndex index)
{
    drawIndex=index.row();
}
